/*
 * PM2: Parallel Multithreaded Machine
 * Copyright (C) 2001 the PM2 team (see AUTHORS file)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

#ifndef __SPINLOCK__
#define __SPINLOCK__ 1

#if defined I686

/* basic spinlock */
typedef struct {
	volatile unsigned int lock;
} spinlock_t;

#define SPINLOCK_UNLOCKED { 1 }


static inline void spin_unlock(spinlock_t * lock)
{
	__asm__ __volatile__("movb $1,%0"
			     : "=m" (lock->lock) : : "memory");

}

static inline int spin_trylock(spinlock_t * lock)
{
	char oldval;
	__asm__ __volatile__("xchgb %b0,%1":"=q"(oldval),
			     "=m"(lock->lock)
			     : "0"(0) : "memory");
	return oldval > 0;
}

static inline void spin_lock(spinlock_t * lock)
{
	__asm__ __volatile__("\n1:\t"
			     "lock ; decb %0\n\t"
			     "jns 3f\n"
			     "2:\t"
			     "rep;nop\n\t"
			     "cmpb $0,%0\n\t"
			     "jle 2b\n\t"
			     "jmp 1b\n\t"
			     "3:\n" : "=m"(lock->lock) : : "memory");
}

#elif defined X86_64

/* basic spinlock */
typedef struct {
	volatile unsigned int lock;
} spinlock_t;

#define SPINLOCK_UNLOCKED { 1 }


static inline void spin_unlock(spinlock_t * lock)
{
	__asm__ __volatile__("movl $1,%0"
			     : "=m" (lock->lock) : : "memory");

}

static inline int spin_trylock(spinlock_t * lock)
{
	int oldval;
	__asm__ __volatile__("xchgl %l0,%1":"=q"(oldval),
			     "=m"(lock->lock)
			     : "0"(0) : "memory");
	return oldval > 0;
}

static inline void spin_lock(spinlock_t * lock)
{
	__asm__ __volatile__("\n1:\t"
			     "lock ; decl %0\n\t"
			     "jns 3f\n"
			     "2:\t"
			     "rep;nop\n\t"
			     "cmpl $0,%0\n\t"
			     "jle 2b\n\t"
			     "jmp 1b\n\t"
			     "3:\n" : "=m"(lock->lock) : : "memory");
}

#else
#error Neither X86_64 nor X86_32 is defined
#endif

#endif /** __SPIN_LOCK__ **/
